package com.rem.concurrency.multithreading.syn;

import cn.hutool.core.date.DateUtil;
import lombok.Data;
import lombok.SneakyThrows;

/**
 * 产生死锁的四个必要条件：
 * <p>
 * 互斥条件：一个资源每次只能被一个进程使用。
 * 请求与保持条件：一个进程因请求资源而阻塞时，对方获得的资源保持不放。
 * 不剥夺条件：进程已获得的资源，在未使用完之前，不能强行剥夺。
 * 循环等待条件：若干资源之间形成一种头尾相接的循环等待资源的关系。
 * 只要破坏上面任意一个或者多个条件就能避免死锁的发生。
 *
 * @author Rem
 * @date 2021-03-05
 */

public class DeadLock {
    public static void main(String[] args) {

        A a = new A("a", "b", 0);
        A b = new A("a", "b", 1);
        new Thread(a).start();
        new Thread(b).start();

    }
}

@Data
class A implements Runnable {

    private final String coke;
    private final String beer;
    private Integer flag;

    public A(String coke, String beer, Integer flag) {
        this.coke = coke;
        this.beer = beer;
        this.flag = flag;
    }

    @SneakyThrows
    @Override
    public void run() {


        //同时抱着对方的锁， 造成死锁现象
        if (flag == 0) {
            synchronized (beer) {
                System.err.println(DateUtil.date());
                Thread.sleep(1000);
                synchronized (coke) {
                    System.err.println(DateUtil.date() + "age");
                }
            }

        } else {
            synchronized (coke) {
                System.err.println(DateUtil.date() + "age");
                Thread.sleep(500);
                synchronized (beer) {
                    System.err.println(DateUtil.date());
                }
            }

        }
    }
}

